package cn.gailvlun.gll.widget.photopicker;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
import android.databinding.ViewDataBinding;
import android.support.annotation.Nullable;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;

import com.alibaba.sdk.android.oss.model.PutObjectRequest;
import com.blankj.utilcode.util.FileUtils;
import com.github.markzhai.recyclerview.BaseViewAdapter;
import com.github.markzhai.recyclerview.BindingViewHolder;
import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.PictureSelectorActivity;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.config.PictureMimeType;
import com.luck.picture.lib.entity.LocalMedia;

import org.reactivestreams.Subscription;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

import cn.gailvlun.gll.R;
import cn.gailvlun.gll.databinding.ItemPhotoPhotoBinding;
import cn.gailvlun.gll.mgr.UploadMgr;
import cn.gailvlun.gll.mgr.UploadResult;
import cn.gailvlun.gll.util.DialogUtil;
import cn.gailvlun.gll.util.LogUtil;
import io.reactivex.FlowableSubscriber;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import rx_activity_result2.Result;
import rx_activity_result2.RxActivityResult;



public class PhotoPicker extends RecyclerView implements PhotoPickerItemAdapter {

    
    private int itemHeight;
    
    private int itemWidth;
    
    private int itemRadius;
    
    private int addImageSrc;
    

    

    
    private int closeImageSrc;
    
    private int closeImageHeight;
    
    private int closeImageWidth;
    
    private int maxSelect;

    private Presenter mPresenter;
    
    
    
    public enum Mode {
        EDIT, VIEW
    }

    
    private Mode mMode = Mode.EDIT;

    private Context mContext;

    public PhotoPicker(Context context) {
        this(context, null);
    }

    public PhotoPicker(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PhotoPicker(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mContext = context;

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.PhotoPicker);
        itemHeight = ta.getDimensionPixelSize(R.styleable.PhotoPicker_itemHeight, dp2px(80));
        itemWidth = ta.getDimensionPixelSize(R.styleable.PhotoPicker_itemWidth, dp2px(80));
        itemRadius = ta.getDimensionPixelSize(R.styleable.PhotoPicker_itemRadius, dp2px(4));
        addImageSrc = ta.getResourceId(R.styleable.PhotoPicker_addImageSrc, R.mipmap.ic_launcher);


        closeImageSrc = ta.getDimensionPixelSize(R.styleable.PhotoPicker_closeImageSrc, R.drawable.ic_photo_picker_close);
        closeImageHeight = ta.getDimensionPixelSize(R.styleable.PhotoPicker_closeImageHeight, dp2px(24));
        closeImageWidth = ta.getDimensionPixelSize(R.styleable.PhotoPicker_closeImageWidth, dp2px(24));
        maxSelect = ta.getInt(R.styleable.PhotoPicker_maxSelect, 4);
        ta.recycle();

        setClipChildren(false);

        init();
        createHandler();
    }

    private PhotoAdapter mAdapter;
    private GridLayoutManager mLayoutManager;
    private List<PhotoItem> fileList = new ArrayList<>();

    private void init() {
        mAdapter = new PhotoAdapter(mContext);
        setAdapter(mAdapter);
        mAdapter.setDecorator(new BaseViewAdapter.Decorator() {
            @Override
            public void decorator(BindingViewHolder holder, int position, int viewType) {
                ViewDataBinding itemBinding = holder.getBinding();
                if (itemBinding instanceof ItemPhotoPhotoBinding) {
                    ((ItemPhotoPhotoBinding) itemBinding).ivClose.setImageResource(closeImageSrc);
                }
            }
        });
        mPresenter = new Presenter();
        mAdapter.setPresenter(mPresenter);

        ItemTouchHelper.Callback callback = new PhotoPickerItemHelper(this);
        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback);
        itemTouchHelper.attachToRecyclerView(this);

        mLayoutManager = new GridLayoutManager(mContext, 4);
        setLayoutManager(mLayoutManager);
    }

    @Override
    public void onDrag(int fromPosition, int toPosition) {
        Log.d("onDrag", "from: " + fromPosition + ", to: " + toPosition);
        Collections.swap(fileList, fromPosition, toPosition);
        mAdapter.notifyItemMoved(fromPosition, toPosition);
    }

    private void createHandler() {
        setOnAddListener(new OnAddListener() {
            @Override
            public void onAdd() {
                int leftNum = maxSelect - fileList.size();
                PictureSelector.create((Activity) getContext())
                        .openGallery(PictureMimeType.ofImage())
                        .maxSelectNum(leftNum)
                        .minSelectNum(1)
                        .imageSpanCount(4)
                        .selectionMode(PictureConfig.MULTIPLE)
                        .previewImage(true)
                        .isCamera(true)
                        .imageFormat(PictureMimeType.PNG)
                        .isZoomAnim(true)
                        .sizeMultiplier(0.5f)
                        .setOutputCameraPath("/camera")
                        .previewEggs(true)
                        .compress(true)
                        .cropCompressQuality(80)
                        .minimumCompressSize(200)
                ;


                RxActivityResult.on((Activity) getContext())
                        .startIntent(new Intent(getContext(), PictureSelectorActivity.class))
                        .subscribe(new Consumer<Result<Activity>>() {
                            @Override
                            public void accept(Result<Activity> activityResult) throws Exception {
                                if (activityResult.resultCode() == Activity.RESULT_OK) {
                                    final Dialog progressDialog = DialogUtil.showIndeterminate(mContext);
                                    progressDialog.setCanceledOnTouchOutside(false);
                                    progressDialog.setCancelable(false);

                                    List<LocalMedia> list = PictureSelector.obtainMultipleResult(activityResult.data());
                                    HashMap<String, String> hashMap = new HashMap<>();
                                    for (LocalMedia localMedia : list) {
                                        String path;
                                        if (localMedia.isCompressed()) {
                                            path = localMedia.getCompressPath();
                                        } else {
                                            path = localMedia.getPath();
                                        }
                                        File file = FileUtils.getFileByPath(path);
                                        final String objectKey = UUID.randomUUID().toString() + "." + FileUtils.getFileExtension(file);
                                        hashMap.put(objectKey, path);
                                    }

                                    UploadMgr.getInstance().upload(hashMap)
                                            .subscribeOn(Schedulers.io())
                                            .observeOn(AndroidSchedulers.mainThread())
                                            .subscribe(new FlowableSubscriber<UploadResult>() {
                                                @Override
                                                public void onSubscribe(Subscription s) {
                                                    s.request(Long.MAX_VALUE);
                                                }

                                                @Override
                                                public void onNext(UploadResult uploadResult) {
                                                    LogUtil.d("upload onNext()");
                                                    PhotoItem photoItem = new PhotoItem();
                                                    photoItem.setOssKey(((PutObjectRequest) uploadResult.getRequest()).getObjectKey());
                                                    fileList.add(photoItem);
                                                    if (mOnUploadMgrListener != null) {
                                                        mOnUploadMgrListener.onNext(uploadResult);
                                                    }
                                                }

                                                @Override
                                                public void onError(Throwable t) {
                                                    LogUtil.d("upload onError()");
                                                    updateByList();
                                                    progressDialog.dismiss();
                                                    DialogUtil.showError(mContext, "上传失败");
                                                    if (mOnUploadMgrListener != null) {
                                                        mOnUploadMgrListener.onError(t);
                                                    }
                                                }

                                                @Override
                                                public void onComplete() {
                                                    LogUtil.d("upload onComplete()");

                                                    updateByList();
                                                    progressDialog.dismiss();
                                                    if (mOnUploadMgrListener != null) {
                                                        mOnUploadMgrListener.onComplete();
                                                    }
                                                }
                                            });
                                }
                            }
                        });
            }
        });
        setOnPhotoClickListener(new OnPhotoClickListener() {
            @Override
            public void onPhotoClick(ImageView iv, String file) {

            }
        });
        setOnCloseListener(new OnCloseListener() {
            @Override
            public void onClose(PhotoItem photoItem) {
                fileList.remove(photoItem);
                updateByList();
            }
        });
    }

    private void updateByList() {
        if (mMode == Mode.EDIT) {
            if (fileList.size() == maxSelect) {
                mAdapter.set(fileList, PhotoAdapter.Type.PHOTO.ordinal());
            } else {
                mAdapter.set(fileList, PhotoAdapter.Type.PHOTO.ordinal());
                mAdapter.add(null, PhotoAdapter.Type.ADD.ordinal());
            }
        } else {
            mAdapter.set(fileList, PhotoAdapter.Type.PHOTO.ordinal());
        }
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

        if (mMode == Mode.EDIT) {
            mAdapter.add(null, PhotoAdapter.Type.ADD.ordinal());
        }
    }

    public List<PhotoItem> getFileList() {
        return fileList;
    }

    public void setPhotoItems(List<PhotoItem> list) {
        fileList.clear();
        fileList.addAll(list);
        updateByList();
        setVisibility(View.VISIBLE);

    }

    public void removePhotoItem(PhotoItem item) {
        fileList.remove(item);
        updateByList();
        if (fileList.size() == 0) {
            setVisibility(View.GONE);
        }
    }

    public void clear() {
        fileList.clear();
        updateByList();
    }

    public interface OnUploadMgrListener {
        void onNext(UploadResult uploadResult);

        void onError(Throwable t);

        void onComplete();
    }

    private OnUploadMgrListener mOnUploadMgrListener;

    public void setOnUploadMgrListener(OnUploadMgrListener listener) {
        mOnUploadMgrListener = listener;
    }

    public interface OnPhotoClickListener {
        void onPhotoClick(ImageView iv, String file);
    }

    public interface OnCloseListener {
        void onClose(PhotoItem photoItem);
    }

    public interface OnAddListener {
        void onAdd();
    }

    private OnPhotoClickListener mOnPhotoClickListener;
    private OnCloseListener mOnCloseListener;
    private OnAddListener mOnAddListener;

    public void setOnPhotoClickListener(OnPhotoClickListener onPhotoClickListener) {
        this.mOnPhotoClickListener = onPhotoClickListener;
    }

    public void setOnCloseListener(OnCloseListener onCloseListener) {
        this.mOnCloseListener = onCloseListener;
    }

    public void setOnAddListener(OnAddListener onAddListener) {
        this.mOnAddListener = onAddListener;
    }

    public class Presenter implements BaseViewAdapter.Presenter {
        public void onAdd() {
            if (mOnAddListener != null) {
                mOnAddListener.onAdd();
            }
        }

        public void onPhotoClick(View iv, PhotoItem item) {
            if (mOnPhotoClickListener != null) {
                mOnPhotoClickListener.onPhotoClick((ImageView) iv, item.getRemoteUrl());
            }
        }

        public void onClose(PhotoItem item) {
            if (mOnCloseListener != null) {
                mOnCloseListener.onClose(item);
            }
        }
    }

    
    public int dp2px(final float dpValue) {
        final float scale = getContext().getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    
    public int px2dp(final float pxValue) {
        final float scale = getContext().getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

    public Presenter getPresenter() {
        return mPresenter;
    }
}
